package com.mkyong.common.controller;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.validation.Valid;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
public class HelloController {

	@Autowired
	private SessionFactory sessionFactory;

	Logger logger = Logger.getLogger(HelloController.class.toString());

	// @RequestMapping(method = RequestMethod.GET)
	@RequestMapping("/welcome")
	public String printWelcome(ModelMap model) {
		logger.info("SESS" + sessionFactory.toString());
		logger.info("SESS" + sessionFactory.toString());
		logger.info("SESS" + sessionFactory.toString());
		logger.info("SESS2ss" + sessionFactory.toString());
		Session session = sessionFactory.openSession();

		// SAVE/////////////////////////////////
		Transaction tx = session.beginTransaction();
		Student student = new Student();
		// student.setId(2);
		student.setName("Jan");
		logger.info("tx1 saved" + session.save(student));
		tx.commit();

		Transaction tx1 = session.beginTransaction();
		Student student1 = new Student();
		student1.setId(1); // jesli generator nie jest ustawiony na assigned to
							// i tak zostanie on u?yty, wi?c tutaj ustawione id
							// nie ma znaczenia
		student1.setName("Jan1");
		logger.info("tx1 saved" + session.save(student1));
		tx1.commit();
		// /SAVE//////////////////////////////////

		// /UPDATE/MERGE//////////////////////////////////
		Transaction tx2 = session.beginTransaction();
		Student student2 = new Student();
		// student2.setId(1);
		student2.setName("Jan2");
		Object o = session.merge(student2); // klasyczny update, obiekt musi
											// mie? oczywi?cie ustawione id
											// odpowiednie, gdy nie ma to id
											// zostanie wygenerowane (wtedy
											// zachowanie jak save)
		tx2.commit();
		logger.info("TO BE EVICTED" + student.getId());
		// session.evict(1);
		Transaction tx3 = session.beginTransaction();
		Student student3 = new Student();
		// je?li inny obiekt o tym samym id jest ju? w sesji to zostanie rzucony
		// wyj?tek - NonUnique, transient (bez id) - rzucenie TransientObject,
		student3.setId(1);
		student3.setName("Jan3Update2");
		session.update(student3); // raczej g??wnie do obiekt?w detached, dzia?a
									// dla transient pod warunkiem podanie id
									// istniej?cego w bazie, ale nie b?d?cego w
									// sesji
		tx3.commit();
		//
		// Transaction tx4 = session.beginTransaction();
		// Student student4 = new Student();
		// //student4.setId(2);
		// student4.setName("Jan4");
		// session.save(student4);
		// tx4.commit();

		model.addAttribute("message", "Spring 3 MVC Hello World");
		return "search2";

	}

	@Autowired
	private SearchCommandValidator shopValidator;

	@InitBinder
	private void initBinder(WebDataBinder binder) {
		binder.setValidator(getShopValidator());
	}

	@RequestMapping("/search")
	public String search(Model model) {
		logger.info("search entry");
		model.addAttribute("searchCommand", new SearchCommand());
		return "search2";
	}

	@RequestMapping("/doSearch")
	public String doSearch(@ModelAttribute @Valid SearchCommand searchCommand,
			BindingResult result) {

		logger.info("ERRORS" + result.hasErrors());
		
		logger.log(Level.INFO, searchCommand.firstName);
		logger.log(Level.INFO, searchCommand.lastName);
		logger.log(Level.INFO, Integer.toString(searchCommand.age));
		return "OK";
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public SearchCommandValidator getShopValidator() {
		return shopValidator;
	}

	public void setShopValidator(SearchCommandValidator shopValidator) {
		this.shopValidator = shopValidator;
	}

}